﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using UnityEngine;

namespace FrameWorkSong
{
    public partial class MonoBehaviourSimplify
    {
        Dictionary<string, IEnumerator> keyValueCoroutine;

        Dictionary<string, IEnumerator> KeyValueCoroutine
        {
            get
            {
                if (keyValueCoroutine == null)
                {
                    keyValueCoroutine = new Dictionary<string, IEnumerator>();
                }
                // Debug.Log("keyValueCoroutine=" + keyValueCoroutine.Count);
                return keyValueCoroutine;
            }
            set
            {

                keyValueCoroutine = value;
                //  Debug.Log("keyValueCoroutine=" + keyValueCoroutine.Count);
            }
        }

        /// <summary>
        /// 径向移动(绝对坐标)
        /// </summary>
        /// <param name="transformSelf">移动物体</param>
        /// <param name="target">目标位置</param>
        /// <param name="time">移动时间</param>
        /// <param name="id">移动控制id</param>
        /// <param name="action">完成返回方法</param>
        public void DoMove(Transform transformSelf, Vector3 target, float time, string id = null, Action action = null)
        {
            IEnumerator coroutine;
            // coroutine = StartCoroutine(DoMoveIE(transformSelf,target, time, action));
            coroutine = DoMoveIE(transformSelf, target, time, action);
            StartCoroutine(coroutine);
            if (id != null)
            {
                KeyValueCoroutine.AddData(id, coroutine);
            }
        }
        /// <summary>
        /// 径向移动(相对坐标)
        /// </summary>
        /// <param name="transformSelf">移动物体</param>
        /// <param name="target">目标位置</param>
        /// <param name="time">移动时间</param>
        /// <param name="id">移动控制id</param>
        /// <param name="action">完成返回方法</param>
        public void DoMoveLocal(Transform transformSelf, Vector3 target, float time, string id = null, Action action = null)
        {
            IEnumerator coroutine;
            // coroutine = StartCoroutine(DoMoveIE(transformSelf,target, time, action));
            coroutine = DoMoveIELocal(transformSelf, target, time, action);
            StartCoroutine(coroutine);
            if (id != null)
            {
                KeyValueCoroutine.AddData(id, coroutine);
            }
        }
        /// <summary>
        /// 旋转
        /// </summary>
        /// <param name="transformSelf"></param>
        /// <param name="target"></param>
        /// <param name="time"></param>
        /// <param name="id"></param>
        /// <param name="action"></param>
        public void DoRotate(Transform transformSelf, Quaternion target, float time, Action action = null, string id = null)
        {
            IEnumerator coroutine;
            // coroutine = StartCoroutine(DoMoveIE(transformSelf,target, time, action));
            coroutine = DoRotateIE(transformSelf, target, time, action);
            StartCoroutine(coroutine);
            if (id != null)
            {
                KeyValueCoroutine.AddData(id, coroutine);
            }
        }
        public void DoRotate(Transform transformSelf, Vector3 target, float time, Action action = null, string id = null)
        {
            DoRotate(transformSelf, Quaternion.Euler(target), time, action, id);
        }
        /// <summary>
        /// 路径移动带自定义旋转
        /// </summary>
        /// <param name="transformSelf"></param>
        /// <param name="target"></param>
        /// <param name="angle"></param>
        /// <param name="time"></param>
        /// <param name="action"></param>
        /// <param name="id"></param>
        public void DoMovePathWithRotate(Transform transformSelf, List<Vector3> target, List<Vector3> angle, float time, bool loop, Action action = null, string id = null)
        {
            //得到总距离
            float disAll = Vector3.Distance(transformSelf.position, target[0]);
            int length = target.Count;
            for (int k = 0; k < length - 1; k++)
            {
                disAll += Vector3.Distance(target[k], target[k + 1]);
            }
            int count = target.Count;
            int i = 0;
            DoMoveGo();
            void DoMoveGo()
            {
                if (i < count)

                {
                    float currentTime = GetTime(transformSelf, target, time, i, disAll);
                    IEnumerator coroutine;
                    Quaternion targetQua = Quaternion.Euler(angle[i]);
                    coroutine = DoMoveWithAngle(transformSelf, target[i], targetQua, currentTime, DoMoveGo);
                    StartCoroutine(coroutine);
                    if (id != null)
                    {
                        KeyValueCoroutine.AddData(id, coroutine);
                    }
                    i++;
                }
                else
                {
                    if (loop)
                    {
                        i = 0;
                        DoMoveGo();
                    }
                    else
                    {

                        action();
                    }

                }
            }
        }
        public void DoMovePathWithRotateForTime(Transform transformSelf, List<Vector3> target, List<Vector3> angle, List<float> time, bool loop, Action action = null, string id = null)
        {
            //得到总距离
            //float disAll = Vector3.Distance(transformSelf.position, target[0]);
            //int length = target.Count;
            //for (int k = 0; k < length - 1; k++)
            //{
            //    disAll += Vector3.Distance(target[k], target[k + 1]);
            //}
            int count = target.Count;
            int i = 0;
            DoMoveGo();
            void DoMoveGo()
            {
                if (i < count)
                {
                    // float currentTime = GetTime(transformSelf, target, 10, i, disAll);
                    IEnumerator coroutine;
                    Quaternion targetQua = Quaternion.Euler(angle[i]);
                    coroutine = DoMoveWithAngle(transformSelf, target[i], targetQua, time[i], DoMoveGo);
                    StartCoroutine(coroutine);
                    if (id != null)
                    {
                        keyValueCoroutine.AddData(id, coroutine);
                    }


                    i++;
                }
                else
                {
                    if (loop)
                    {
                        i = 0;
                        DoMoveGo();
                    }
                    else
                    {

                        action();
                    }

                }
            }
        }
        /// <summary>
        /// 路径径向移动
        /// </summary>
        /// <param name="transformSelf">移动物体</param>
        /// <param name="target">目标位置数组</param>
        /// <param name="time">移动时间</param>
        /// <param name="isRotate">是否旋转</param>
        /// <param name="id">移动控制id</param>
        /// <param name="action">完成返回方法</param>
        public void DoMovePath(Transform transformSelf, List<Vector3> target, float time, bool isRotate, Action action = null, string id = null)
        {

            //得到总距离
            float disAll = Vector3.Distance(transformSelf.position, target[0]);
            int length = target.Count;
      
            for (int k = 0; k < length - 1; k++)
            {
                disAll += Vector3.Distance(target[k], target[k+1]);
                disAll += Vector3.Distance(transformSelf.position, target[k]);
                disAll += Vector3.Distance(target[k], target[k + 1]);
            }
            int count = target.Count;
            int i = 0;
            DoMoveGo();
            void DoMoveGo()
            {
                if (i < count)
                {
                    // Debug.Log(id + "=++"+ KeyValueCoroutine.Count);
                    float currentTime = GetTime(transformSelf, target, time, i, disAll);
                    if (isRotate)
                    {
                        Vector3 angle = (Quaternion.LookRotation(target[i] - transformSelf.position, Vector3.up)).eulerAngles;
                        transformSelf.eulerAngles = new Vector3(0, angle.y, 0);
                    }
                    IEnumerator coroutine;
                    coroutine = DoMoveIE(transformSelf, target[i++], currentTime, DoMoveGo);
                    StartCoroutine(coroutine);
                    if (id != null)
                    {
                        KeyValueCoroutine.AddData(id, coroutine);
                    }
                }
                else
                {



                    action();

                }
            }
        }
        public void DoMovePath(Transform transformSelf, List<Vector3> target, float time, bool isRotate, bool loop, Action action = null, string id = null)
        {

            //得到总距离
            float disAll = Vector3.Distance(transformSelf.position, target[0]);
            int length = target.Count;
            for (int k = 0; k < length - 1; k++)
            {
                disAll += Vector3.Distance(target[k], target[k + 1]);
            }
            int count = target.Count;
            int i = 0;
            DoMoveGo();
            void DoMoveGo()
            {
                if (i < count)
                {
                    // Debug.Log(id + "=++"+ KeyValueCoroutine.Count);
                    float currentTime = GetTime(transformSelf, target, time, i, disAll);
                    if (isRotate)
                    {
                        Vector3 angle = (Quaternion.LookRotation(target[i] - transformSelf.position, Vector3.up)).eulerAngles;
                        transformSelf.eulerAngles = new Vector3(0, angle.y, 0);
                    }
                    IEnumerator coroutine;
                    coroutine = DoMoveIE(transformSelf, target[i++], currentTime, DoMoveGo);
                    StartCoroutine(coroutine);
                    if (id != null)
                    {
                        KeyValueCoroutine.AddData(id, coroutine);
                    }
                }
                else
                {

                    if (loop)
                    {
                        i = 0;
                        DoMoveGo();
                    }
                    else
                    {

                        action();
                    }
                }
            }
        }
        /// <summary>
        /// 路径径向水平移动
        /// </summary>
        /// <param name="transformSelf">移动物体</param>
        /// <param name="target">目标位置数组</param>
        /// <param name="time">移动时间</param>
        /// <param name="isRotate">是否旋转</param>
        /// <param name="id">移动控制id</param>
        /// <param name="action">完成返回方法</param>
        public void DoMovePathLevel(Transform transformSelf, List<Vector3> target, float time, bool isRotate, Action action = null, string id = null)
        {
            //得到总距离
            float disAll = Vector3.Distance(transformSelf.position, target[0]);
            int length = target.Count;
            for (int k = 0; k < length - 1; k++)
            {
                disAll += Vector3.Distance(target[k], target[k + 1]);
            }
            int count = target.Count;
            int i = 0;
            //  float currentTime = time / count;
            DoMoveGo();
            void DoMoveGo()
            {
                if (i < count)
                {
                    float currentTime = GetTime(transformSelf, target, time, i, disAll);
                    if (isRotate)
                    {
                        Vector3 angle = (Quaternion.LookRotation(target[i] - transformSelf.position, Vector3.up)).eulerAngles;
                        transformSelf.eulerAngles = new Vector3(0, angle.y, 0);
                    }
                    IEnumerator coroutine;
                    // coroutine = StartCoroutine(DoMoveIE(transformSelf, target[i++], currentTime, DoMoveGo));
                    coroutine = DoMoveIELevel(transformSelf, target[i++], currentTime, DoMoveGo);
                    StartCoroutine(coroutine);
                    if (id != null)
                    {
                        KeyValueCoroutine.AddData(id, coroutine);
                    }
                }
                else
                {
                    action();
                }
            }
        }
        /// <summary>
        /// 通过距离算时间
        /// </summary>
        /// <param name="transformSelf"></param>
        /// <param name="target"></param>
        /// <param name="time"></param>
        /// <param name="k"></param>
        /// <param name="disAll"></param>
        /// <returns></returns>
        float GetTime(Transform transformSelf, List<Vector3> target, float time, int k, float disAll)
        {
            float dis = Vector3.Distance(transformSelf.position, target[k]);
            return time * (dis / disAll);
        }
        public void DoMoveY(Transform transformSelf, float y, float time, string id = null, Action action = null)
        {
            IEnumerator coroutine;

            coroutine = DoMoveIEY(transformSelf, y, time, action);
            StartCoroutine(coroutine);
            if (id != null)
            {
                KeyValueCoroutine.AddData(id, coroutine);
            }

        }

        /// <summary>
        /// 时间插值
        /// </summary>
        /// <param name="time">插值时间</param>
        /// <param name="id">ID</param>
        /// <param name="action">返回方法</param>
        public void DoTime(float time, Action<float> action, string id = null)
        {

            IEnumerator coroutine;
            coroutine = DoTimeIE(time, action);
            StartCoroutine(coroutine);
            if (id != null)
            {
                KeyValueCoroutine.AddData(id, coroutine);
            }

        }
        /// <summary>
        /// 时间延迟
        /// </summary>
        /// <param name="time"></param>
        /// <param name="action"></param>
        /// <param name="id"></param>
        public void DoDelayTime(float time, Action action, string id = null)
        {

            IEnumerator coroutine;
            coroutine = DelayTimeIE(time, action);
            StartCoroutine(coroutine);
            if (id != null)
            {
                KeyValueCoroutine.AddData(id, coroutine);
            }

        }
        /// <summary>
        /// 停止变化
        /// </summary>
        /// <param name="id"></param>
        public void StopSongTween(string id)
        {
            if (KeyValueCoroutine.ContainsKey(id))
            {
                IEnumerator coroutine = KeyValueCoroutine[id];
                StopCoroutine(coroutine);
            }
        }
        /// <summary>
        /// 继续变化
        /// </summary>
        /// <param name="id"></param>
        public void StartSongTween(string id)
        {
            if (KeyValueCoroutine.ContainsKey(id))
            {
                IEnumerator coroutine = KeyValueCoroutine[id];
                StartCoroutine(coroutine);
            }
        }

        public void DoStringRead(string stringInfo, float time, Action<string> action, string id = null)
        {
            //byte[] infos = Encoding.UTF8.GetBytes(stringInfo);
            //Debug.Log(infos.Length);
            //List<string> stringInfos=new List<string>();
            //for (int i = 0; i < infos.Length-2; i+=2)
            //{
            //    byte[] newString = new byte[3];
            //    newString[0] = infos[i];
            //    newString[1] = infos[i+1];
            //    newString[2] = infos[i+2];
            //    stringInfos.Add( Encoding.UTF8.GetString(newString));
            //}
            //List<string> stringInfos = new List<string>();
            Char[] stringInfos = stringInfo.ToCharArray();
            // Debug.Log(info.Length);
            IEnumerator coroutine;
            coroutine = DoStringReadIE(stringInfos, time, action);
            StartCoroutine(coroutine);
            if (id != null)
            {
                KeyValueCoroutine.AddData(id, coroutine);
            }
        }
        IEnumerator DoMoveWithAngle(Transform transformSelf, Vector3 target, Quaternion targetQua, float time, Action action = null)
        {
            Vector3 selfPoint = transformSelf.position;
            Quaternion formQua = transformSelf.rotation;
            float t = 0;
            while (t < 1)
            {
                t += Time.deltaTime / time;
                t = t > 1 ? 1 : t;
                transformSelf.position = (1 - t) * selfPoint + t * target;
                transformSelf.rotation = Quaternion.Lerp(formQua, targetQua, t);
                yield return null;
            }
            transformSelf.position = target;
            transformSelf.rotation = targetQua;
            if (action != null)
            {
                action();
            }
        }
        IEnumerator DoMoveIE(Transform transformSelf, Vector3 target, float time, Action action = null)
        {
            Vector3 selfPoint = transformSelf.position;
            float t = 0;
            while (t < 1)
            {
                t += Time.deltaTime / time;
                t = t > 1 ? 1 : t;
                transformSelf.position = (1 - t) * selfPoint + t * target;
                yield return null;
            }
            transformSelf.position = target;
            if (action != null)
            {
                action();
            }
        }
        IEnumerator DoMoveIELevel(Transform transformSelf, Vector3 target, float time, Action action = null)
        {
            Vector3 selfPoint = transformSelf.position;
            Vector3 targetLevel = new Vector3(target.x, selfPoint.y, target.z);
            float t = 0;
            while (t < 1)
            {
                t += Time.deltaTime / time;
                t = t > 1 ? 1 : t;
                transformSelf.position = (1 - t) * selfPoint + t * targetLevel;
                yield return null;
            }
            transformSelf.position = targetLevel;
            if (action != null)
            {
                action();
            }
        }
        IEnumerator DoRotateIE(Transform transformSelf, Quaternion targetQua, float time, Action action = null)
        {
            Quaternion formQua = transformSelf.rotation;
            float t = 0;
            while (t < 1)
            {
                t += Time.deltaTime / time;
                t = t > 1 ? 1 : t;
                transform.rotation = Quaternion.Lerp(formQua, targetQua, t);
                yield return null;
            }
            transform.rotation = targetQua;
            if (action != null)
            {
                action();
            }
        }
        IEnumerator DoMoveIELocal(Transform transformSelf, Vector3 target, float time, Action action = null)
        {
            Vector3 selfPoint = transformSelf.localPosition;
            float t = 0;
            while (t < 1)
            {
                t += Time.deltaTime / time;
                t = t > 1 ? 1 : t;
                transformSelf.localPosition = (1 - t) * selfPoint + t * target;
                yield return null;
            }
            transformSelf.localPosition = target;
            if (action != null)
            {
                action();
            }

        }
        IEnumerator DoTimeIE(float time, Action<float> action = null)
        {

            float t = 0;
            while (t < 1)
            {
                t += Time.deltaTime / time;
                if (action != null)
                {
                    action(t);
                }
                t = t > 1 ? 1 : t;
                yield return null;
            }
            action(1);
        }
        IEnumerator DelayTimeIE(float time, Action action = null)
        {

            float t = 0;
            while (t < 1)
            {
                t += Time.deltaTime / time;

                t = t > 1 ? 1 : t;
                yield return null;
            }
            if (action != null)
            {
                action();
            }
        }
        IEnumerator DoMoveIEY(Transform transformSelf, float y, float time, Action action = null)
        {
            Vector3 selfPoint = transformSelf.position;
            float t = 0;
            while (t < 1)
            {
                t += Time.deltaTime / time;
                t = t > 1 ? 1 : t;
                transformSelf.position = new Vector3(selfPoint.x, (1 - t) * selfPoint.y + t * y, selfPoint.z);
                yield return null;
            }
            if (action != null)
            {
                action();
            }

        }
        IEnumerator DoStringReadIE(Char[] stringInfos, float time, Action<string> action = null)
        {
            float t = 0;
            float count = 0;
            float stringCount = stringInfos.Length;
            float newTime = time / stringCount;
            while (count <= stringCount)
            {
                t += Time.deltaTime / newTime;
                //t = t > 1 ? 0 : t;
                if (t > 1)
                {
                    string infos = "";
                    for (int i = 0; i < count; i++)
                    {
                        infos += stringInfos[i];
                    }
                    action(infos);
                    count++;
                    t = 0;
                }
                yield return null;
            }
        }
    }
}